package com.sjx.audiotest

import com.sjx.jnistudy.MainActivity2
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.sin

object MockData {

    init {
        System.loadLibrary("calc-utils")
    }

    val freq = intArrayOf(
        400,
        450,
        500,
        550,
        600,
        650,
        700,
        750,
        800,
        850,
        900,
        950,
        1000,
        1050,
        1100,
        1150,
        1200,
        1250,
        1300,
        1350,
        1400,
        1450,
        1500,
        1550,
        1600,
        1650,
        1700,
        1750,
        1800,
        1850,
        1900,
        1950
    )

    fun getListDefalutData(): ArrayList<ListBean> {
        val list = ArrayList<ListBean>()
        val startHz = 400
        for (i in 0 until 32) {
            val hz = 400
            list.add(ListBean((400 + 50 * i), 0))
        }
        return list
    }

    fun getMockFd(): IntArray {
        return IntArray(32) { 0 }
    }

    const val twoPI = 2 * Math.PI

    var offsets = ArrayList<Int>()
    var hasSout = false

    /**
     * 方案一
     */
    fun getWaveData(
        list: ArrayList<ListBean>,
        sampleRate: Int,
        updatePriodMs: Int,
        maxProgress: Int = 100
    ): ByteArray {

        if (offsets.size == 0) {
            repeat(list.size) { offsets.add(0) }
        }

        val len = sampleRate / 1000 * updatePriodMs
        val temp = twoPI * 1.0f / sampleRate

        //val p = list.size * maxProgress * 1.0 / 127

        val bytes = ByteArray(len)

        val doubles = DoubleArray(len)
        doubles.fill(0.0)
        bytes.fill(0)

        for (i in 0 until list.size) {
            val item = list[i]
            val pointsNumberPerPeriod = sampleRate / item.name
            // item 频率，幅度
//            val byte0 = 0
//            val byte1:

            for (j in 0 until len) {
                doubles[j] += item.progress * sin(temp * (j + offsets[i]) * item.name)
            }
            //offsets[i] += len % pointsNumberPerPeriod
            //offsets[i] %= pointsNumberPerPeriod
        }

        val dmax = max(doubles.max() ?: 0.0, abs(doubles.min() ?: 0.0))
        var listProgressMax = list[0].progress
        list.forEach {
            if (listProgressMax < it.progress) listProgressMax = it.progress
        }
        val p = listProgressMax * 1.0 / maxProgress * 127 / dmax

        for (i in doubles.indices) {
            bytes[i] = (doubles[i] * p).toByte()
        }
        return bytes
    }


    /**
     * 方案二
     */
    fun buildBaseWave(
        sampleRate: Int,
        barNum: Int = 32,
        progressGroup: Int = 20,
        updatePriodMs: Int = 100,
        startFreq: Int = 400,
        stepFreq: Int = 50
    ): ArrayList<ArrayList<ArrayList<Double>>> {
        val list = ArrayList<ArrayList<ArrayList<Double>>>()
        val temp = twoPI * 1.0f / sampleRate
        val size = sampleRate / 1000 * updatePriodMs
        for (i in 0 until barNum) {
            val list1 = ArrayList<ArrayList<Double>>()
            for (j in 0 until progressGroup) {
                val list2 = ArrayList<Double>()
                for (k in 0 until size) {
                    list2.add(j * sin(temp * k * (startFreq + i * stepFreq)))
                }
                list1.add(list2)
            }
            list.add(list1)
        }
        return list

    }

    /**
     * barProgress 幅度
     */
    fun getWaveDataFromBase(
        barProgress: ArrayList<Int>,
        sampleRate: Int = 8000,
        updatePriodMs: Int = 100,
        maxProgress: Int = 100,
        progressGroup:Int = 20
    ): ByteArray {
        val size = sampleRate / 1000 * updatePriodMs
        val bytes = ByteArray(size)

        val doubles = DoubleArray(size)
        doubles.fill(0.0)
        bytes.fill(0)
        for (i in 0 until barProgress.size) {
            var progressGroupIndex = barProgress[i] * progressGroup / maxProgress
            if(progressGroupIndex >= progressGroup) progressGroupIndex = progressGroup - 1
            for (j in 0 until size){
                doubles[j] += MainActivity2.baseWave!![i][progressGroupIndex][j]
            }
        }
        val dmax = max(doubles.max() ?: 0.0, abs(doubles.min() ?: 0.0))
        val listProgressMax = barProgress.max() ?: 0

        val p = listProgressMax * 1.0 / maxProgress * 127 / dmax
        for (i in doubles.indices) {
            bytes[i] = (doubles[i] * p).toByte()
        }
        return bytes

    }


    /**
     * 方案三
     */
    fun buildBaseWaveByte(
        sampleRate: Int,
        barNum: Int = 32,
        progressGroup: Int = 20,
        updatePriodMs: Int = 100,
        startFreq: Int = 400,
        stepFreq: Int = 50
    ): ArrayList<ArrayList<ByteArray>> {
        val list = ArrayList<ArrayList<ByteArray>>()
        val temp = twoPI * 1.0f / sampleRate
        val size = sampleRate / 1000 * updatePriodMs
        for (i in 0 until barNum) {
            val list1 = ArrayList<ByteArray>()
            for (j in 0 until progressGroup) {
                val list2 = ByteArray(size)
                for (k in 0 until size) {
                    list2[k] = (j*127/progressGroup * sin(temp * k * (startFreq + i * stepFreq))).toByte()
                }
                list1.add(list2)
            }
            list.add(list1)
        }
        return list

    }

    fun getWaveDataFromBaseByte(
        barProgress: ArrayList<Int>,
        sampleRate: Int = 8000,
        updatePriodMs: Int = 100,
        maxProgress: Int = 100,
        progressGroup:Int = 20
    ): ByteArray {
        var maxBarProgress = 0
        var maxBarProgressIndex = 0
        for (i in barProgress.indices){
            if (barProgress[i] > maxBarProgress){
                maxBarProgress = barProgress[i]
                maxBarProgressIndex = i
            }
        }
        var progressGroupIndex = maxBarProgress * progressGroup / maxProgress
        if(progressGroupIndex >= progressGroup) progressGroupIndex = progressGroup - 1
        return MainActivity2.baseWaveByte!![maxBarProgressIndex][progressGroupIndex]

    }
}